import { ConfigHelper } from "../app_base/module/config/ConfigHelper";
import { app } from "../base";

export class JsonConfigHelper<DataStructure> extends ConfigHelper<DataStructure>{
    /**
     * 加载配置，固定失败重试次数为3次
     * @param onComplete 
     * @param caller 
     * @param path 
     * @returns 
     */
    loadData(onComplete?: (error: Error, config: ConfigHelper<DataStructure>) => void, caller?: any, path?: string): ConfigHelper<DataStructure> {
        path = path || this._path;
        this._path = path;
        if (!this._path) {
            onComplete && onComplete.apply(caller, [new Error("path 数据为空"), this]);
            return this;
        }
        app.res.load<cc.JsonAsset>(this._path).then((asset) => {
            this.setData(asset.json);
            onComplete && onComplete.apply(caller, [null, this]);
        });
        return this;
    }

    /**
     * 字段值匹配 查询表中的一行
     * 表有多行数据匹配字段值时,取第一个匹配成功的
     * @param key 查询键名
     * @param value 查询键值
     */
    public fetchOneByValue<T>(key: string, value: any): T {
        if (!this.data || !(Array.isArray(this.data))) {
            return null;
        }
        let result: T = null;
        for (const cfg of this.data) {
            if (cfg && cfg.hasOwnProperty(key) && cfg[key] === value) {
                result = cfg;
                break;
            }
        }
        return result;
    }

    /**
      * 字段值匹配 查询表中的所有行
      * @param key 查询键名
      * @param value 查询键值
      */
    public fetchAllByValue<T>(key: string, value: any): T[] {
        let result: T[] = [];
        if (!this.data || !(Array.isArray(this.data))) {
            return result;
        }
        for (const obj of this.data) {
            if (key in obj && obj[key] === value) {
                result.push(obj);
            }
        }
        return result;
    }

    /**
      * 字段值匹配 查询表中的所有行
      * 值可以是多个，只要有一个符合要求即匹配通过
      * @param key 查询键名
      * @param value 查询键值
      */
    public fetchAllByAnyValue<T>(key: string, values: any[]): T[] {
        let result: T[] = [];
        if (!this.data || !(Array.isArray(this.data))) {
            return result;
        }
        for (const obj of this.data) {
            if (key in obj && values.includes(obj[key])) {
                result.push(obj);
            }
        }
        return result;
    }

    /**
      * 多字段值匹配 查询表中的一行
      * 该行数据与参数指定的多个字段全部匹配成功才返回
      * 表有多行数据匹配字段秒多个值时,取第一个匹配成功的
      * @param obj 多键值对
      */
    public fetchOneByMul<T>(obj: { [k: string]: any; }): T {
        if (!this.data || !(Array.isArray(this.data))) {
            return null;
        }
        let result: T = null;
        let oKeys = Object.keys(obj);
        for (const cfg of this.data) {
            let isMatch = oKeys.every(key => {
                return cfg && cfg.hasOwnProperty(key) && obj[key] === cfg[key];
            });
            if (isMatch) {
                result = cfg;
                break;
            }
        }
        return result;
    }

    /**
     * 多字段值匹配 查询表中的多行
     * 这些行与参数指定的多个字段全部匹配才返回
     * @param obj 多键值对
     */
    public fetchAllByMul<T>(obj: { [k: string]: any; }): T[] {
        if (!this.data || !(Array.isArray(this.data))) {
            cc.warn('请保证 loadJson 函数已执行完成');
            return null;
        }
        let result: T[] = [];
        let oKeys = Object.keys(obj);
        for (const cfg of this.data) {
            let isMatch = oKeys.every(key => {
                return cfg && cfg.hasOwnProperty(key) && obj[key] === cfg[key];
            });
            if (isMatch) {
                result.push(cfg);
            }
        }
        return result;
    }

    /**
     * 字段值匹配 
     * 查询表中匹配该字段及其值的行在表的索引号
     * 有多行字段值匹配取第一个匹配成功的
     * @param key 查询键名
     * @param value 查询键值
     */
    findIndex(key: string, value: any) {
        if (!this.data || !(Array.isArray(this.data))) {
            return -1;
        }
        let result = -1;
        for (let i = 0; i < this.data.length; i++) {
            const cfg = this.data[i];
            if (cfg && cfg.hasOwnProperty(key) && cfg[key] === value) {
                result = i;
                break;
            }
        }
        return result;
    }
}